import SingleClass from "../base/SingleClass";

/**

/**
 * EventManager 是事件派发器类，负责进行事件的发送和侦听。
 */
export default class EventManager extends SingleClass {
  /**事件 */
  private events: ObjectString<EventBin[]> = {};
  /**一次性事件 */
  private onceEvents: ObjectString<EventBin[]> = {};

  /**
   * 注册事件
   * @param type 事件类型
   * @param listener 回调喊出
   * @param thisObj 作用域
   */
  public on(type: string, listener: Function, thisObj: any): void {
    let list: EventBin[] = this.events[type];
    if (!list) {
      list = this.events[type] = [];
    }
    list.push({ listener, thisObj });
  }

  /**
   * 一次性事件
   * @param type 事件类型
   * @param listener 回调喊出
   * @param thisObj 作用域
   */
  public once(type: string, listener: Function, thisObj: any): void {
    let list: EventBin[] = this.onceEvents[type];
    if (!list) {
      list = this.onceEvents[type] = [];
    }
    list.push({ listener, thisObj });
  }

  /**
   * 发送事件
   * @param type
   * @param args
   */
  public emit(type: string, ...args): void {
    let list: EventBin[] = this.events[type];
    if (list) {
      for (let i = 0, len = list.length; i < len; i++) {
        let event = list[i];
        event.listener.apply(event.thisObj, args);
      }
    }
    //一次性事件
    list = this.onceEvents[type];
    if (list) {
      for (let i = 0, len = list.length; i < len; i++) {
        let event = list[i];
        event.listener.apply(event.thisObj, args);
      }
      delete this.onceEvents[type];
    }
  }

  /**移除事件 */
  public off(type: string, listener: Function, thisObj: any): void {
    let list: EventBin[] = this.events[type];
    if (list) {
      let index = this.find(list, listener, thisObj);
      if (index != -1) {
        list.splice(index, 1);
      }
    }
    //一次性事件
    list = this.onceEvents[type];
    if (list) {
      let index = this.find(list, listener, thisObj);
      if (index != -1) {
        list.splice(index, 1);
      }
    }
  }
  /**查找 */
  private find(list: EventBin[], listener: Function, thisObj: any): number {
    if (list) {
      for (let i = 0, len = list.length; i < len; i++) {
        let event = list[i];
        if (event.listener == listener && event.thisObj == thisObj) {
          return i;
        }
      }
    }
    return -1;
  }

  /**
   * 移除所有某类型事件
   * @param type
   **/
  public removeTypeAll(type: string): void {
    let list1: EventBin[] = this.events[type];
    let list2: EventBin[] = this.onceEvents[type];
    if (list1) delete this.events[type];
    if (list2) delete this.onceEvents[type];
  }

  /**移除所有事件 */
  public offAll(): void {
    this.events = {};
    this.onceEvents = {};
  }
}

interface EventBin {
  /**
   * @private
   */
  listener: Function;
  /**
   * @private
   */
  thisObj: any;
}

interface ObjectString<T> {
  [str: string]: T;
}
